﻿import mx.utils.Delegate;
import caurina.transitions.Equations;
import caurina.transitions.Tweener;

import kliment.ApplicationAbstract;
import kliment.controls.ListBox;
import kliment.controls.ListBoxBtnItemAbstract;
import kliment.controls.Orientation;
import kliment.controls.Scroller;
import kliment.controls.ScrollerBox;
import kliment.display.MCC;
import kliment.display.SpriteBtn;
import kliment.layout.Canvas;
import kliment.geom.SimplePoint;
import kliment.display.Sprite;
/**
 * ...
 * @author	Kliment
 * @version	1.4.10
 */
class kliment.controls.ComboBox extends SpriteBtn {
	private var _parent_mc:MovieClip;
	private var _speedAnimation:Number = .4;
	private var _target_box_cell:Canvas;
	private var _list_box_cell:Canvas;
	private var _list_box:ListBox;
	private var _content_mc:MovieClip;
	private var _layout_buttons_mc:MovieClip;
	private var _layout_focus_mc:MovieClip;
	private var _box_identifier:String;
	private var _isShow:Boolean = false;
	private var _isDownPos:Boolean = true;
	private var _rowCount:Number = 5;
	private var _itenRender:Function;
	private var _dataProvider:Array;
	private var _scroller:Scroller;
	private var _scrollerBox:ScrollerBox;
	private var _selectedIndex:Number = -1;
	private var _selectedItem:ListBoxBtnItemAbstract;
	private var _hidePosition:Number;
	
	/**
	Events:
		onChange(target:ComboBox)
		onClose(target:ComboBox)
		onDataChange(target:ComboBox)
		onItemRollOver(target:ComboBox, item:ListBoxBtnItemAbstract)
		onItemRollOut(target:ComboBox, item:ListBoxBtnItemAbstract)
		onOpen(target:ComboBox)
	**/
	
	public function ComboBox(target_mc:MovieClip, box_identifier:String) {
		super(target_mc);
		_parent_mc = ApplicationAbstract.instance.layout_top_mc;
		_box_identifier = box_identifier;
		addListener(this);
		Stage.addListener(this);
	}
	
	private function onRelease():Void {
		if (_target_box_cell) {
			if (_isShow) 
				close();
			else
				open();
		} else {
			_create();
		}
	}
	
	public function get value() {
		return selectedItem;
	}
	
	private function _create():Void {
		_target_box_cell = new Canvas(MCC.create(_parent_mc));
		
		_target_box_cell.visible = false;
		_content_mc = MCC.attach(_box_identifier, _target_box_cell.content_mc);
		_list_box_cell = new Canvas(_content_mc.content_box_mc, null, null, true);
		
		_layout_focus_mc = MCC.create(_list_box_cell.content_mc);
		_layout_buttons_mc = MCC.create(_list_box_cell.content_mc);
		
		_createList();
		
		_setPosition();
		_content_mc._y = _hidePosition;
		
		Key.addListener(this);
		Mouse.addListener(this);
		open();
		_target_box_cell.target_mc.onEnterFrame = Delegate.create(this, _setPosition);
	}
	
	private function _createList():Void {
		var listener:Object = new Object();
		listener.onRollOver = Delegate.create(this, _onRollOverHandler);
		listener.onRollOut = 
		listener.onReleaseOutside = Delegate.create(this, _onRollOutHandler);
		listener.onPress = Delegate.create(this, _onRelease);
		
		_list_box = new ListBox(_layout_buttons_mc, Orientation.VERTICAL);
		_list_box.sharedData = { comboBox:this, listener:listener };
		_list_box.itemRender = _itenRender;
		_list_box.dataProvider = _dataProvider;
		var w:Number = Math.max(width, _layout_buttons_mc._width);
		_target_box_cell.width = w;
		_list_box.width = w
		_list_box_cell.width = w;
		_updateRowCount();
		
		if (_selectedIndex > -1) {
			var item = _list_box.getItem(_selectedIndex);
			item.setFocus();
			selectedIndex = _selectedIndex;
			
			_scroller.showPart(item.y, item.y + item.height);
		}
	}
	
	private function _updateRowCount():Void {
		_scrollerBox = new ScrollerBox(_content_mc.scroller_mc);
		var lashShow:Sprite = _list_box.getItem(_rowCount - 1);
		if (lashShow) {
			_list_box_cell.height = lashShow.y + lashShow.height;
			_target_box_cell.height = lashShow.y + lashShow.height;
		} else {
			_list_box_cell.updateHeight();
			_target_box_cell.height = _list_box_cell.height;
		}
		
		_scrollerBox.space_mc._height = _list_box_cell.height;
		_scroller = new Scroller(_list_box_cell.content_mc, _list_box_cell.mask_mc, 
								{
									scrollerBox:_scrollerBox, 
									orientation:Orientation.VERTICAL, 
									scaleSeeker:true, 
									keyboardEnable:false,
									mouseGestureEnable:false
								});
	}
	
	private function _onRelease(target:ListBoxBtnItemAbstract):Void {
		if (target.index != _selectedIndex) {
			var old = _list_box.getItem(_selectedIndex);
			old.resetFocus();
			selectedIndex = target.index;
		}
		close();
	}
	
	private function _onRollOverHandler(target:ListBoxBtnItemAbstract):Void {
		target.setFocus();
		broadcastMessage('onItemRollOver', this, target);
	}
	
	private function _onRollOutHandler(target:ListBoxBtnItemAbstract):Void {
		target.resetFocus();
		broadcastMessage('onItemRollOut', this, target);
	}
	
	private function _setPosition():Void {
		var pos:SimplePoint = MCC.translatePosition(_target_mc, _parent_mc);
		
		var tpos:SimplePoint = new SimplePoint();
		_parent_mc.globalToLocal(tpos);
		var th:Number = pos.y - tpos.y;
		
		var bpox:SimplePoint = new SimplePoint(0, Stage.height);
		_parent_mc.globalToLocal(bpox);
		var bh:Number = bpox.y - pos.y - height;
		
		_target_box_cell.x = pos.x;
		
		if (bh >= _target_box_cell.height) {
			_target_box_cell.y = pos.y + height;
			_hidePosition = -_list_box_cell.height;
			_isDownPos = true;
		} else {
			_target_box_cell.y = pos.y - _target_box_cell.height;
			_hidePosition = _target_box_cell.height;
			_isDownPos = false;
		}
	}
	
	public function get itemRender():Function { return _itenRender }
	public function set itemRender(class_name:Function):Void {
		_itenRender = class_name;
		if (_target_box_cell)
			_createList();
	}
	
	public function get dataProvider():Array { return _dataProvider }
	public function set dataProvider(value:Array):Void {
		_dataProvider = value;
		if (_target_box_cell)
			_createList();
		broadcastMessage('onDataChange', this);
	}
	
	public function get selectedIndex():Number { return _selectedIndex }
	public function set selectedIndex(index:Number):Void {
		var c_index:Number = _selectedIndex;
		if (_list_box) {
			var item = _list_box.getItem(index);
			_selectedItem = item;
			_selectedIndex = (_selectedItem)?index: -1;
		} else {
			_selectedIndex = index;
		}
		if (c_index != index)
			broadcastMessage('onChange', this);
	}
	
	public function get rowCount():Number { return _rowCount; }
	public function set rowCount(value:Number):Void {
		_rowCount = Math.max(1, value);
		if (_target_box_cell)
			_updateRowCount();
	}
	
	public function get selectedItem():Object { return _dataProvider[_selectedIndex] }
	
	public function open():Void {
		_isShow = true;
		_target_box_cell.visible = true;
		Tweener.addTween(_content_mc, { time:_speedAnimation, _y:0, transition:Equations.easeOutCirc } );
	}
	
	public function close():Void {
		if (_isShow) {
			_isShow = false;
			Tweener.addTween(_content_mc, {_y:_hidePosition, time:_speedAnimation, transition:Equations.easeInCubic, onComplete:Delegate.create(this, _remove) } );
		}
	}
	
	private function onMouseDown():Void {
		if (!_inSpace()) {
			close();
		}
	}
	
	private function onMouseWheel():Void {
		if (!_inSpace()) {
			_remove()
		}
	}
	
	private function onKeyDown():Void {
		/*var keyCode:Number = Key.getCode();
		switch(keyCode) {
			case Key.UP:
				selectedIndex--;
			break;
			
			case Key.DOWN:
				selectedIndex++;
			break;
		}*/
	}
	
	private function _inSpace():Boolean {
		if (!MCC.hitTestMouse(_target_box_cell.target_mc) && !MCC.hitTestMouse(_target_mc))
			return false;
		return true;
	}
	
	private function _remove():Void {
		_scroller.remove();
		delete _scroller;
		Tweener.removeTweens(_content_mc);
		Mouse.removeListener(this);
		Key.removeListener(this);
		_list_box.remove();
		delete _list_box;
		_target_box_cell.remove();
		delete _target_box_cell;
		broadcastMessage('onClose', this);
	}
	
	private function onResize():Void {
		if (_target_box_cell) {
			close();
			_remove();
		}
	}
	
	public function remove():Void {
		_remove();
		Stage.removeListener(this);
		super.remove();
	}
}